#include <assert.h>
#include "CanvasContainer.h"

CCanvasContainer::CCanvasContainer()
{
    m_canvas.SetContainer(this);
}

CCanvasContainer::~CCanvasContainer()
{
}

void CCanvasContainer::CanvasSizeChanged()
{
    BOOL foo;
    OnSize(0, 0, 0, foo);
}

void CCanvasContainer::GetViewPortion(RECT &rc)
{
    RECT rcCanvas;
    GetClientRect(&rc);
    GetWindowRect(&rcCanvas);
    ScreenToClient(&rcCanvas);
    IntersectRect(&rc, &rcCanvas, &rc);
    rc.right -= rc.left;
    rc.bottom -= rc.top;
    rc.left = rc.top = 0;

    long xPos = GetScrollPos(SB_HORZ);
    long yPos = GetScrollPos(SB_VERT);
    
    rc.left += xPos;
    rc.right += xPos;
    rc.top += yPos;
    rc.bottom += yPos;
}

void CCanvasContainer::SetErrorInfoWindow (HWND hErrWnd)
{
    m_canvas.SetErrorInfoWindow( hErrWnd);
}

HWND CCanvasContainer::CreatePaneWindow(HWND hParent, RECT& rc, DWORD dwStyle, DWORD dwExStyle)
{
    assert (hParent);
    
    dwExStyle |=  WS_EX_CLIENTEDGE;
    dwStyle |= WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
    m_hWnd = Create (hParent, rc, NULL, dwStyle, dwExStyle);

    if (!m_hWnd) {
        DWORD err = GetLastError();
        return NULL;
    }
    ::ShowWindow(m_hWnd, SW_SHOW);
    ::UpdateWindow(m_hWnd);
    return m_hWnd;
}

LRESULT CCanvasContainer::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    m_rcCanvas.left = 0;
    m_rcCanvas.top = 0;
    m_rcCanvas.right = m_canvas.m_doc.m_uCanvasWidth;
    m_rcCanvas.bottom = m_canvas.m_doc.m_uCanvasHeight;

    m_canvas.Create(m_hWnd, m_rcCanvas);
    m_canvas.CenterWindow();
    m_canvas.GetWindowRect(&m_rcCanvas);

    ScreenToClient(&m_rcCanvas);
    return 0;
}

LRESULT CCanvasContainer::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    return 0;
}
 
LRESULT CCanvasContainer::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    RECT rc, rcCanvas;
    GetClientRect(&rc);
    rcCanvas.left = 0;
    rcCanvas.right = m_canvas.m_doc.m_uCanvasWidth;
    rcCanvas.top = 0;
    rcCanvas.bottom = m_canvas.m_doc.m_uCanvasHeight;

    if (rc.right < rcCanvas.right) {
        SetScrollRange(SB_HORZ, 0,  (rcCanvas.right-rc.right), FALSE);
        ShowScrollBar (SB_HORZ, TRUE);
    } else {
        ShowScrollBar (SB_HORZ, FALSE);
    }
    if (rc.bottom < rcCanvas.bottom) {
        SetScrollRange(SB_VERT, 0,  (rcCanvas.bottom-rc.bottom), FALSE);
        ShowScrollBar (SB_VERT, TRUE);
    } else {
        ShowScrollBar (SB_VERT, FALSE);
    }

    m_canvas.CenterWindow();
    m_canvas.GetWindowRect(&m_rcCanvas);
    ScreenToClient(&m_rcCanvas);

    return 0;
}

#define SCROLL_PAGE 50


LRESULT CCanvasContainer::OnScroll(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	bHandled = TRUE;
    RECT rc, rcCanvas;
    GetClientRect(&rc);
    rcCanvas.left = 0;
    rcCanvas.right = m_canvas.m_doc.m_uCanvasWidth;
    rcCanvas.top = 0;
    rcCanvas.bottom = m_canvas.m_doc.m_uCanvasHeight;

	WORD wCode = LOWORD(wParam);
	if (wCode == SB_ENDSCROLL)
		return 0;

	int nBar = (uMsg == WM_HSCROLL ? SB_HORZ : SB_VERT);
	long lPos = GetScrollPos(nBar);

    if (nBar == SB_HORZ) {
        lPos = CalcSBPos (wParam, lPos, rcCanvas.right - rc.right);
        MoveCanvas(-lPos, NOMOVE);    
    } else if (nBar == SB_VERT) {
        lPos = CalcSBPos (wParam, lPos, rcCanvas.bottom - rc.bottom);
        MoveCanvas(NOMOVE, -lPos);    
    } 
    SetScrollPos(nBar, lPos);
    Invalidate();
    return 0;
}

int CCanvasContainer::CalcSBPos (WPARAM wParam, long curPos, long upperlimit)
{
    WORD wCode = LOWORD (wParam);

    switch (wCode) {
	case SB_LINELEFT:
        (curPos > 0 ? curPos -- : curPos = 0);
		break;
	case SB_PAGELEFT:
        (curPos - SCROLL_PAGE > 0 ? curPos = (curPos - SCROLL_PAGE) : curPos = 0);
		break;
	case SB_LINERIGHT:
        if (curPos < upperlimit) {
            curPos++;
        }
		break;
	case SB_PAGERIGHT:
        if (curPos + SCROLL_PAGE < upperlimit) {
            curPos = curPos + SCROLL_PAGE;
        } else {
            curPos = upperlimit;
        }
		break;
	case SB_THUMBPOSITION:
	case SB_THUMBTRACK:
		curPos = HIWORD(wParam);
		break;
	}
    return curPos;
}

void CCanvasContainer::MoveCanvas (int x, int y)
{
    if (x > NOMOVE) {
        m_rcCanvas.left = x;
        m_rcCanvas.right = m_rcCanvas.left + m_canvas.m_doc.m_uCanvasWidth;
    }
    if (y > NOMOVE) {
        m_rcCanvas.top = y;
        m_rcCanvas.bottom = m_rcCanvas.top + m_canvas.m_doc.m_uCanvasHeight;
    }

    m_canvas.MoveWindow(&m_rcCanvas, FALSE);
}

